export default class Utils {

    static parseUrl() {
        var params = {};
        if (window.location == null) {
            return params;
        }
        var name, value;
        var str = window.location.href; //取得整个地址栏
        var num = str.indexOf("?");
        str = str.substr(num + 1); //取得所有参数   stringvar.substr(start [, length ]
        var arr = str.split("&"); //各个参数放到数组里
        for (let i = 0; i < arr.length; i++) {
            num = arr[i].indexOf("=");
            if (num > 0) {
                name = arr[i].substring(0, num);
                value = arr[i].substr(num + 1);
                params[name] = value;
            }
        }
        return params;
    }

    static getUtf8Length = function (str: string) {
        let totalLength = 0;
        for (let i = 0; i < str.length; i++) {
            let charCode = str.charCodeAt(i);
            if (charCode < 0x007f) {
                totalLength++;
            } else if ((0x0080 <= charCode) && (charCode <= 0x07ff)) {
                totalLength += 2;
            } else if ((0x0800 <= charCode) && (charCode <= 0xffff)) {
                totalLength += 3;
            }
        }
        return totalLength;
    };

    static strToBuffer(str: string) {
        let val = '';
        for (let i = 0; i < str.length; i++) {
            val += ',' + code2utf8(str.charCodeAt(i))
        }
        val += ',00';
        // 将16进制转化为ArrayBuffer
        return new Uint8Array(val.match(/[\da-f]{2}/gi).map(function (h) {
            return parseInt(h, 16)
        })).buffer;

        function code2utf8(uni) {
            let uni2 = uni.toString(2);
            if (uni < 128) {
                return uni.toString(16);
            } else if (uni < 2048) {
                uni2 = ('00000000000000000' + uni2).slice(-11);
                const s1 = parseInt("110" + uni2.substring(0, 5), 2);
                const s2 = parseInt("10" + uni2.substring(5), 2);
                return s1.toString(16) + ',' + s2.toString(16)
            } else {
                uni2 = ('00000000000000000' + uni2).slice(-16);
                const s1 = parseInt('1110' + uni2.substring(0, 4), 2);
                const s2 = parseInt('10' + uni2.substring(4, 10), 2);
                const s3 = parseInt('10' + uni2.substring(10), 2);
                return s1.toString(16) + ',' + s2.toString(16) + ',' + s3.toString(16)
            }
        }
    }

    static code2utf8(uni) {
        let uni2 = uni.toString(2)
        if (uni < 128) {
            return uni.toString(16);
        } else if (uni < 2048) {
            uni2 = ('00000000000000000' + uni2).slice(-11);
            const s1 = parseInt("110" + uni2.substring(0, 5), 2);
            const s2 = parseInt("10" + uni2.substring(5), 2);
            return s1.toString(16) + ',' + s2.toString(16)
        } else {
            uni2 = ('00000000000000000' + uni2).slice(-16);
            const s1 = parseInt('1110' + uni2.substring(0, 4), 2);
            const s2 = parseInt('10' + uni2.substring(4, 10), 2);
            const s3 = parseInt('10' + uni2.substring(10), 2);
            return s1.toString(16) + ',' + s2.toString(16) + ',' + s3.toString(16)
        }
    }

    /*数字开头补0*/
    static numberFormat(num: number, bit: number): string {
        let count = num.toString().length - bit;
        if (count < 0) {
            let str = [].init(-count, 0).join('');
            return str + num;
        }
        return num.toString();
    }

    static removeFrontNum0(str: string) {
        return str.replace(/\b(0+)/gi, "");
    }

    /*获取数组中重复次数的值*/
    static getRepeatCount(arr: number[], count: number): number[] {
        const res = {};
        arr.forEach((key) => {
            if (res[key]) {
                res[key]++;
            } else {
                res[key] = 1;
            }
        });
        let values = [];
        for (let key in res) {
            if (res[key] >= count) {
                values.push(+key);
            }
        }
        return values;
    }

    /*用户名字限制验证*/
    static regUserName(name: string, count: number = 7) {
        let reg = /^[\u4e00-\u9fa5]$|^[\dA-Za-z]$/;
        let arr = name.split('');
        let max = 3 * count;
        for (let i = 0; i < arr.length; i++) {
            if (!reg.test(arr[i])) {
                return false;
            }
            let len = this.getUtf8Length(arr[i]) === 3 ? 3 : 3 / 2;
            max -= len;
            if (max < 0) {
                return false;
            }
        }
        return true;
    }

    /*标准洗牌算法*/
    static getShuffle<T>(arr: T[]): T[] {
        for (let i = 0; i < arr.length; i++) {
            let index = Math.floor(Math.random() * arr.length);
            [arr[index], arr[i]] = [arr[i], arr[index]];
        }
        return arr;
    }

    /*数组中取随机数*/
    static getNumToArray(arr: any[]): any {
        let index = Math.floor(Math.random() * arr.length);
        return arr[index];
    }

    /*范围取随机数*/
    static getNumMinToMax(min: number, max: number): number {
        return Math.floor(Math.random() * (max - min + 1)) + min;
    }
    /*随机方向*/
    static getRandomDir(): number {
        return Math.random() > 0.5 ? 1 : -1;
    }
    //按权重进行随机
    static weightsRadom(weights: number[]): number {
        //求权重和
        let weightSum = 0;
        weights.forEach(element => {
            weightSum += element;
        });
        // console.log('-----------权重和:', weightSum);

        //获取一个随机数
        let radom = Math.random() * weightSum;
        // console.log('-----------随机数:', radom);

        //判断所在的区间
        let weightsCount = 0;
        for (let i = 0; i < weights.length; i++) {
            weightsCount += weights[i];
            if (radom < weightsCount) {
                // console.log('-----------随机结果下标:', i);
                return i;
            }
        }
    }

    static getProbability(arr: number[], bit: number = 2): number {
        let num = +Math.random().toFixed(bit);
        let sum = 0;
        for (let i = 0; i < arr.length; i++) {
            sum += arr[i];
            if (sum >= num) {
                return i;
            }
        }
    }
    /**/
    static getDate(time: number, format?: string): string {
        let date = new Date(time);
        let y = date.getFullYear();
        let m = date.getMonth() + 1;
        let d = date.getDate();
        let h = date.getHours();
        let min = date.getMinutes();
        let s = date.getSeconds();
        return `${y}/${this.numberFormat(m, 2)}/${this.numberFormat(d, 2)} ${this.numberFormat(h, 2)}:${this.numberFormat(min, 2)}`;
    }

    static getShowDate(time: number): string {
        let date = new Date(time);
        let h = Utils.numberFormat(date.getHours(), 2);
        let min = Utils.numberFormat(date.getMinutes(), 2);
        let m = Utils.numberFormat(date.getMonth() + 1, 2);
        let d = Utils.numberFormat(date.getDate(), 2);
        let day = 3600 * 24 * 1000;
        if (Date.now() - time < day) {
            return `今天 ${h}:${min}`;
        } else if (Date.now() - time < day * 2) {
            return `昨天 ${h}:${min}`;
        } else if (Date.now() - time < day * 3) {
            return `三天前 ${h}:${min}`;
        }
        return `${m}-${d} ${h}:${min}`;
    }

    static getTimeRange(start_time: number, end_time: number): string {
        let date = new Date(end_time - start_time);
        let m = Utils.numberFormat(date.getMinutes(), 2);
        let s = Utils.numberFormat(date.getSeconds(), 2);
        return `${m}:${s}`;
    }
    static formatMinSeconds(time: number) {
        let min = Math.floor(time / 60);
        let second = Math.floor(time % 60);
        let m = Utils.numberFormat(min, 2);
        let s = Utils.numberFormat(second, 2);
        return `${m}:${s}`;
    }
    static getNum(text: string): number {
        return +text.replace(/[^\d]/ig, '');
    }
    /*随机分解一个数到数组*/
    static getArrToNum(sum: number, size: number): number[] {
        let arr = [];
        const min = 1;
        let max, money;
        let sign = Math.sign(sum);
        sum = Math.abs(sum);
        while (size > 1) {
            max = sum / size * 2;
            money = Math.random() * max;
            money = money < min ? min : money;
            money = Math.round(money);
            arr.push(money * sign);
            size--;
            sum -= money;
        }
        arr.push(Math.round(sum) * sign);
        return arr;
    }
    static getRandomNumToStr(str: string): { n: number, str: string } {
        let i = (str.indexOf('['));
        let j = (str.indexOf(']'));
        if (i < 0 || j < 0) {
            return { n: 0, str: str };
        }
        let s = str.slice(i + 1, j);
        let arr = s.split('-').map(value => +value);
        let n = Utils.getNumMinToMax(arr[0], arr[1]);
        return { n, str: str.replace(s, n.toString()) };
    }

    static getDisTwoPos(pos1: cc.Vec2, pos2: cc.Vec2, no_sqrt: boolean = false): number {
        let offset_x = (pos1.x - pos2.x);
        let offset_y = (pos1.y - pos2.y);
        if (no_sqrt) {
            return (offset_x * offset_x + offset_y * offset_y);
        } else {
            return Math.sqrt(offset_x * offset_x + offset_y * offset_y);
        }
    }

     /**随机获取一个角色周围的坐标 range <= 2: 获取屏幕外坐标*/
     static getRadomPos(heroPos: cc.Vec2, range: number = 2, allSize: boolean = false): cc.Vec2 {
        let endPos: cc.Vec2 = cc.v2();
        let radom = Math.random() * 1;
        let x = 0;
        let y = 0;
        if (radom < 0.25) {//右侧
            x = 1280 / range;
            if(allSize)x = this.getNumMinToMax(-x, x);
            let height = 720 / range;
            y = this.getNumMinToMax(-height, height);
        } else if (radom < 0.5) {
            x = -1280 / range;
            if(allSize)x = this.getNumMinToMax(x, -x);
            let height = 720 / range;
            y = this.getNumMinToMax(-height, height);
        } else if (radom < 0.7) {
            let width = 1280 / range;
            x = this.getNumMinToMax(-width, width);
            y = 720 / range;
            if(allSize)y = this.getNumMinToMax(-y, y);
        } else {
            let width = 1280 / range;
            x = this.getNumMinToMax(-width, width);
            y = -720 / range;
            if(allSize)y = this.getNumMinToMax(y,-y);
        }
        endPos.x = heroPos.x + x;
        endPos.y = heroPos.y + y;

        return endPos;
    }

    static getAngle(p1: cc.Vec2, p2: cc.Vec2) {
        var angle = Math.atan2(((p2.y) - p1.y), (p2.x - p1.x)) //弧度  0.6435011087932844
        var theta = angle * 180 / Math.PI; //角度  36.8698976458440
        return theta
    };


     // 角度转弧度
    static angle_to_radian(angle: number): number {
        // 角度转弧度公式
        // π / 180 * 角度

        // 计算出弧度
        let radian = Math.PI / 180 * angle;
        // 返回弧度
        return (radian);
    }

    // 角度转向量   
    static angle_to_vector(angle: number): cc.Vec2 {
        // tan = sin / cos
        // 将传入的角度转为弧度
        let radian = this.angle_to_radian(angle);
        // 算出cos,sin和tan
        let cos = Math.cos(radian);// 邻边 / 斜边
        let sin = Math.sin(radian);// 对边 / 斜边
        // 结合在一起并归一化
        let vec = new cc.Vec2(cos, sin).normalize();
        // 返回向量
        return (vec);
    }
    
    // 弧度转角度
    static radian_to_angle(radian: number): number {
        // 弧度转角度公式
        // 180 / π * 弧度

        // 计算出角度
        let angle = 180 / Math.PI * radian;
        // 返回弧度
        return (angle);
    }

    /**
     * 向量转角度  
     * @param v2 归一化向量
     */
    static vector_to_angle(v2: cc.Vec2): number{
        // 计算出目标角度的弧度
        let radian = v2.signAngle(new cc.Vec2(1, 0));
        // 把弧度计算成角度
        let angle = -this.radian_to_angle(radian);
        // 返回角度
        return (angle);
    }
}